package com.zygh.lz.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.img.Img;
import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONObject;
import com.zygh.lz.stapprove.InBean;
import com.zygh.lz.stapprove.OutBean;
import com.zygh.lz.stapprove.OutBeanUtil;
import com.zygh.lz.stapprove.ResultUtil;
import com.zygh.lz.vo.CommonResult;
import com.zygh.lz.vo.ResultBean;
import com.zygh.lz.vo.ResultBeans;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@RestController
@Api(tags = "上传文件", description = "FileUpload")
public class FileUpload {

    //@Value("${file.upload}")
    private static String uploadDir = "D:/dlqw/picture/";
    //@Value("${file.ip}")
    private static String ip = "62.66.6.163";

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");

    private static final Logger log = LoggerFactory.getLogger("FileUpload");

    /**
     * 多张图片上传
     *
     * @param file 文件
     * @return CommonResult
     */
    @ApiOperation("PC端调用上传文件方法")
    @PostMapping("fileUpload")
    public ResultBean uploadImages(MultipartFile[] file) {
        //long startTime = System.currentTimeMillis();
        String[] urls = new String[file.length];
        for (int i = 0; i < file.length; i++) {
            Object data = uploadImage(file[i]).getData();
            if (data != null) {
                urls[i] = (String) data;
            }
        }
        //long endTime = System.currentTimeMillis();
        return ResultUtil.setOK("上传成功", urls);
    }


    /**
     * 图片上传
     *
     * @param file 文件
     * @return CommonResult
     */
    public CommonResult uploadImage(MultipartFile file) {
        String uuid = UUID.randomUUID().toString();
        // 文件名
        String originalFilename = file.getOriginalFilename();
        // 后缀名
        String suffixName = originalFilename.substring(originalFilename.lastIndexOf('.'));
        // 图片存储路径
        Date date = new Date();
        String format = simpleDateFormat.format(date.getTime());
        String filePath = uploadDir + format + "/";
        // 新文件名
        String fileName = uuid + suffixName;
        //图片访问路径
        String imageUrl = format + "/" + fileName;
        String storagePath = filePath + fileName;

        File dest = new File(storagePath);
        if (!dest.exists()) {
            dest.mkdirs();
        }

        try {
            file.transferTo(dest);
            Img.from(FileUtil.file(storagePath))
                    .setQuality(0.8)//压缩比率
                    .write(FileUtil.file(storagePath));
            return new CommonResult().success(imageUrl);
        } catch (IOException e) {
            return new CommonResult().failed().validateFailed("文件上传失败");
        }
    }


    @PostMapping("ReadPictures")
    public String ReadPictures(String site) {
        return FileUpload.ReadPicture(site);
    }

    /**
     * 本地图片转成base64返回前端
     *
     * @param site 图片存储路径
     * @return Object
     */
    public static String ReadPicture(String site) {
        byte[] temp = null;
        String path = "D:/dlqw/picture/" + site;
        //String path = uploadDir + site;
        try {
            File file = new File(path);//注意此处读取的数据库路径
            //应该是自己图片存储的路径C:\Users\Administrator\Desktop\test\001\2019.png
            FileInputStream fis = new FileInputStream(file);
            long size = file.length();
            temp = new byte[(int) size];
            /*
            *   b - 读取数据的缓冲区。
                off - 目标数组 b的起始偏移量
                len - 读取的最大字节数。
            * */
            fis.read(temp, 0, (int) size);
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (StringUtils.isEmpty(Base64.encode(temp))) {
            return null;
        }
        String baseStr = "data:image/jpeg;base64," + Base64.encode(temp);
        //String baseStr = Base64.encode(temp);

        return baseStr;
    }

    /**
     * 本地图片转成base64返回前端
     *
     * @param path 图片存储路径
     * @return 图片存储全路径
     */
    public static String ReadPictureByPath(String path) {
        if (Base64.isBase64(path)) {
            return path;
        }
        byte[] temp = null;
        //String path = uploadDir + site;
        try {
            File file = new File(path);//注意此处读取的数据库路径
            //应该是自己图片存储的路径C:\Users\Administrator\Desktop\test\001\2019.png
            FileInputStream fis = new FileInputStream(file);
            long size = file.length();
            temp = new byte[(int) size];
            /*
            *   b - 读取数据的缓冲区。
                off - 目标数组 b的起始偏移量
                len - 读取的最大字节数。
            * */
            fis.read(temp, 0, (int) size);
            fis.close();
        } catch (IOException e) {
            throw new IllegalArgumentException("无法读取图片数据");
        } catch (NullPointerException e) {
            throw new IllegalArgumentException("图片地址为空");
        }
        if (StringUtils.isEmpty(Base64.encode(temp))) {
            throw new IllegalArgumentException("base64Data 数据不合法");
        }
        String baseStr = Base64.encode(temp);
        //String baseStr = Base64.encode(temp);

        return baseStr;
    }

    /**
     * app 调用方法
     *
     * @return
     */

    public OutBean uploadPicture(String base64Data, @RequestBody(required = false) InBean inBean) {
        JSONObject jsonObject = inBean.convertObj(JSONObject.class);
        base64Data = jsonObject.getString("problemPicture");
        ResultBeans resultBeans = ResultUtil.resultBeansSuccess(this.uploadImage(base64Data));
        return OutBeanUtil.resSuc(resultBeans, inBean);
    }

    @ApiOperation("APP调用上传文件方法")
    @PostMapping("uploadPictures")
    public List<String> uploadPictures(List<String> list) {
        List<String> image = new ArrayList<>();
        //JSONObject jsonObject = inBean.convertObj(JSONObject.class);
        //String problemPicture = jsonObject.getString("problemPicture");
        //net.sf.json.JSONArray dataJson = net.sf.json.JSONArray.fromObject(problemPicture);
        //List<String> list = (List<String>) JSONArray.toCollection(dataJson, String.class);
        for (String base64Datum : list) {
            String s = this.uploadImage(base64Datum);
            image.add(s);
        }
        return image;
    }


    /**
     * 接受Base64格式文件
     *
     * @param base64Data Base64格式文件（传参带头一起传）
     * @return ResultBean
     */
    public String uploadImage(String base64Data) {
        //base64格式前头
        String dataPrix = "";
        //实体部分数据
        String data = "";
        if (base64Data == null || "".equals(base64Data)) {
            return "上传失败，上传图片数据为空";
        } else {
            //将字符串分成数组
            String[] d = base64Data.split("base64,");
            if (d.length >= 2) {
                dataPrix = d[0];
                data = d[1];
            } else {
                return "上传失败，数据不合法";
            }
        }
        String suffix = "";//图片后缀，用以识别哪种格式数据
        //编码的jpeg图片数据
        if ("data:image/jpeg;".equalsIgnoreCase(dataPrix) || "data:image/jpg;".equalsIgnoreCase(dataPrix)) {
            suffix = ".jpg";
        } else if ("data:image/x-icon;".equalsIgnoreCase(dataPrix)) {
            //编码的icon图片数据
            suffix = ".ico";
        } else if ("data:image/gif;".equalsIgnoreCase(dataPrix)) {
            //编码的gif图片数据
            suffix = ".gif";
        } else if ("data:image/png;".equalsIgnoreCase(dataPrix)) {
            //编码的png图片数据
            suffix = ".png";
        } else {
            return "上传图片格式不合法";

        }
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        String tempFileName = System.currentTimeMillis() + uuid + suffix;
        Date date = new Date();
        String format = simpleDateFormat.format(date.getTime());
        String imgFilePath = uploadDir + format + "/" + tempFileName;//新生成的图片

        File filePath = new File(uploadDir + format + "/");
        // 如果保存文件的地址不存在，就先创建目录
        if (!filePath.exists()) {
            filePath.mkdirs();
        }

        BASE64Decoder decoder = new BASE64Decoder();
        try {
            //Base64解码
            byte[] b = decoder.decodeBuffer(data);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    //调整异常数据
                    b[i] += 256;
                }
            }
            OutputStream out = new FileOutputStream(imgFilePath);

            out.write(b);
            out.flush();
            out.close();
            String imgurl = format + "/" + tempFileName;
            return imgurl;
        } catch (IOException e) {
            e.printStackTrace();
            return "上传图片失败";

        }

    }

    /**
     * 接受Base64格式文件
     *
     * @param base64Data Base64格式文件
     * @param uploadDir  存储路径
     * @return String 文件路径
     */
    public static String uploadImage(String base64Data, String uploadDir) throws IOException {
        //base64格式前头
        String dataPrix = "";
        //实体部分数据
        String data = "";
        String suffix = ".jpg";//图片后缀，用以识别哪种格式数据
        if (base64Data == null || "".equals(base64Data)) {
            throw new IllegalArgumentException("base64Data 是空的");
        } else {
            //将字符串分成数组
            if (base64Data.contains("base64,")) {
                String[] d = base64Data.split("base64,");
                if (d.length >= 2) {
                    dataPrix = d[0];
                    data = d[1];
                } else {
                    throw new IllegalArgumentException("base64Data 数据不合法");
                }
                //编码的jpeg图片数据
                if ("data:image/jpeg;".equalsIgnoreCase(dataPrix) || "data:image/jpg;".equalsIgnoreCase(dataPrix)) {
                    suffix = ".jpg";
                } else if ("data:image/x-icon;".equalsIgnoreCase(dataPrix)) {
                    //编码的icon图片数据
                    suffix = ".ico";
                } else if ("data:image/gif;".equalsIgnoreCase(dataPrix)) {
                    //编码的gif图片数据
                    suffix = ".gif";
                } else if ("data:image/png;".equalsIgnoreCase(dataPrix)) {
                    //编码的png图片数据
                    suffix = ".png";
                } else {
                    throw new IllegalArgumentException("无法识别图片后缀");
                }
            } else {
                data = base64Data;
            }

        }


        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        String tempFileName = System.currentTimeMillis() + uuid + suffix;
        Date date = new Date();
        String format = simpleDateFormat.format(date.getTime());
        String imgFilePath = uploadDir + format + "/" + tempFileName;//新生成的图片

        File filePath = new File(uploadDir + format + "/");
        // 如果保存文件的地址不存在，就先创建目录
        if (!filePath.exists()) {
            filePath.mkdirs();
        }

        log.info("存储base64图片：文件名：[{}];base64:[{}]", imgFilePath, base64Data);
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            //Base64解码
            byte[] b = decoder.decodeBuffer(data);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    //调整异常数据
                    b[i] += 256;
                }
            }
            OutputStream out = new FileOutputStream(imgFilePath);

            out.write(b);
            out.flush();
            out.close();
            return format + "/" + tempFileName;
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        }

    }

    /**
     * 压缩图片至40k之内，将原图片的长宽分别压缩为原图片的1/3，如果图片大小大于40k，则继续进行压缩。
     *
     * @param base64Img
     * @return
     */
    public static String resizeImageTo40K(String base64Img) {
        try {
            BufferedImage src = base64String2BufferedImage(base64Img);
            BufferedImage output = Thumbnails.of(src).size(src.getWidth() / 3, src.getHeight() / 3).asBufferedImage();
            String base64 = imageToBase64(output);
            if (base64.length() - base64.length() / 8 * 2 > 40000) {
                output = Thumbnails.of(output).scale(1 / (base64.length() / 40000)).asBufferedImage();
                base64 = imageToBase64(output);
            }
            return base64;
        } catch (Exception e) {
            return base64Img;
        }
    }

    //base64转换成BufferedImage:
    public static BufferedImage base64String2BufferedImage(String base64string) {
        BufferedImage image = null;
        try {
            InputStream stream = BaseToInputStream(base64string);
            image = ImageIO.read(stream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return image;
    }

    //Base64转换成InputStream:
    private static InputStream BaseToInputStream(String base64string) {
        ByteArrayInputStream stream = null;
        try {
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] bytes1 = decoder.decodeBuffer(base64string);
            stream = new ByteArrayInputStream(bytes1);
        } catch (Exception e) {
            // TODO: handle exception
        }
        return stream;
    }

    //BufferedImage转换成base64，在这里需要设置图片格式，如下是jpg格式图片：
    public static String imageToBase64(BufferedImage bufferedImage) {
        Base64 encoder = new Base64();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write(bufferedImage, "jpg", baos);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new String(Base64.encode((baos.toByteArray())));
    }


}
